// 实现一个简单的事件发布——订阅模式
let salesOffices: SalesOffice = {// 售卖处
    clientList: [],// 客户列表
    addClient(callback: Function) {// 添加客户
        this.clientList.push(callback);
    },
    noticeClient(...params: any[]) {// 通知客户
        for (let i = 0; i < this.clientList.length; i++) {
            this.clientList[i].apply(this, params);
        }
    }
};
salesOffices.addClient(function (price: number) {
    console.log('LEON是我的客户');
    console.log(`Leon看上的番茄的价格是${price}`);
});
salesOffices.addClient(function (price: number) {
    console.log('Amy也是我的客户');
    console.log(`Amy看上的番茄的价格是${price}`);
});

// 测试用例
salesOffices.noticeClient(100);// Amy和Leon都会同时收到消息
salesOffices.noticeClient(666);// Amy和Leon都会同时收到消息


// 实现一个通过key值管理的事件发布——订阅模式
let newSalesOffices: ImproveSalesOffice = {// 售卖处
    clientList: {},// 客户列表
    addClient(key: string, callback: Function) {// 添加客户
        if (!this.clientList[key]) {// 如果该事件没有被订阅过，初始化一个队列
            this.clientList[key] = [];
        }
        this.clientList[key].push(callback);
    },
    noticeClient(key: string, ...params: any[]) {// 通知客户
        if (!this.clientList[key]) {
            console.log('没有订阅的事件触发');
            return false;
        }
        for (let i = 0; i < this.clientList[key].length; i++) {
            this.clientList[key][i].apply(this, params);
        }
    }
};

// 测试用例 
newSalesOffices.addClient('房价', function (price: number) {
    console.log('房价现在是' + price);
})
newSalesOffices.noticeClient('房价', 1000000);// 房价现在是1000000
newSalesOffices.noticeClient('车价', 100000);// 没有订阅的事件触发


// 为对象动态添加事件发布——订阅模式
const em: EventManager = {
    subscribers: {},// 订阅者哈希表
    listen(key: string, callback: Function) {// 添加订阅
        if (!this.subscribers[key]) {// 如果该事件没有被订阅过，初始化一个队列
            this.subscribers[key] = [];
        }
        this.subscribers[key].push(callback);
    },
    trigger(key: string, ...params: any[]) {// 通知事件
        if (!this.subscribers[key]) {
            console.log('没有订阅的事件触发');
            return false;
        }
        for (let i = 0; i < this.subscribers[key].length; i++) {
            this.subscribers[key][i].apply(this, params);
        }
    }
};
// 为对象动态添加事件发布订阅职责
function addEventManager(target: any) {
    return Object.assign(target, em);
}

// 测试用例
let testObj: any = {};
addEventManager(testObj);
testObj.listen('房价', function (price: number) {
    console.log('房价现在是' + price);
})
testObj.trigger('房价', 1000000);// 房价现在是1000000
testObj.trigger('车价', 100000);// 没有订阅的事件触发
console.dir(testObj);


// 为对象动态添加事件发布——订阅模式(添加了移除订阅功能)
const improveEm: ImproveEventManager = {
    subscribers: {},// 订阅者哈希表
    listen(key: string, callback: Function) {// 添加订阅
        if (!this.subscribers[key]) {// 如果该事件没有被订阅过，初始化一个队列
            this.subscribers[key] = [];
        }
        this.subscribers[key].push(callback);
    },
    trigger(key: string, ...params: any[]) {// 通知事件
        if (!this.subscribers[key]) {
            console.log('没有订阅的事件触发');
            return false;
        }
        for (let i = 0; i < this.subscribers[key].length; i++) {
            this.subscribers[key][i].apply(this, params);
        }
    },
    remove(key: string, callback?: Function) {
        const callbackQueue = this.subscribers[key];
        if (callbackQueue.length === 0) {// 如果没有被订阅过则直接返回
            console.log('没有被订阅的事件');
            return false;
        }
        if (!callback) {
            this.subscribers[key] = [];// 如果没有传入的回调函数，则默认为取消所有的订阅事件
        } else {
            for (let i = 0; i < this.subscribers[key].length; i++) {
                if (this.subscribers[key][i] === callback) {// 删除订阅者的回调函数
                    this.subscribers[key].splice(i,1);
                }
            }
        }
    }
};

// 测试用例
const fn1 = function (price: number) {
    console.log('来自fn1：房价现在是' + price);
};
const fn2 = function (price: number) {
    console.log('来自fn2：房价现在是' + price);
};
improveEm.listen('房价',fn1);
improveEm.listen('房价',fn2);
improveEm.trigger('房价',20000000);// fn1\fn2都触发
improveEm.remove('房价',fn1);
improveEm.trigger('房价',100000);// 只有fn1触发
